#ifndef __K_MST_ILP__H__
#define __K_MST_ILP__H__

#include "Tools.h"
#include "Instance.h"
#include <ilcplex/ilocplex.h>

using namespace std;

ILOSTLBEGIN

struct EdgeVar
{
	IloBoolVar* e; // 1 iff the edge has been selected for the k-MST tree, 0 otherwise
	unsigned weight;
	unsigned start; // index of start vertex
	unsigned end; // index of end vertex
	vector<IloNumVar*> f; // flow variables for each commodity, f[0] is nullptr, for 1 <= i <= n-1: f[i] is flow of commodity i on this edge
};

struct EdgeVarIP
{
	IloBoolVar* e; // 1 iff the edge has been selected for the k-MST tree, 0 otherwise
	unsigned weight;
	unsigned start; // index of start vertex
	unsigned end; // index of end vertex
	vector<IloBoolVar*> f; // flow variables for each commodity, f[0] is nullptr, for 1 <= i <= n-1: f[i] is flow of commodity i on this edge
};

class kMST_ILP
{



private:

	// input data
	Instance& instance;
	string model_type;
	int k;
	unsigned numVariables;
	unsigned numConstraints;
	// number of edges and nodes including root node and root edges
	unsigned int m, n;

	vector<list<EdgeVar*>> incoming;
	vector<list<EdgeVar*>> outgoing;

	IloEnv env;
	IloModel model;
	IloCplex cplex;

	IloBoolVar** adj;
	vector<IloNumVar*> orderVars;

	void modelSCF();
	void modelMCF();	
	void modelMTZ();

	void modelMCF2();
	void modelMCF2IPFLOW();
	void modelObjectiveFunction();

public:

	// describes one directed edge for the MCF model	

	kMST_ILP( Instance& _instance, string _model_type, int _k );
	~kMST_ILP();
	void solve();

private:

	void setCPLEXParameters();
	bool isSolutionFeasible();

};
// kMST_ILP

#endif //__K_MST_ILP__H__
